package com.module.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.module.common.BaseController;
import com.module.common.Constant;
import com.module.listen.OnlineSession;
import com.module.listen.SessionListener;
import com.module.user.domain.BaseResp;
import com.module.user.domain.EditUserReq;
import com.module.user.domain.ForgetPwdReq;
import com.module.user.domain.LoginReq;
import com.module.user.domain.ModifyPwdReq;
import com.module.user.domain.RegisterReq;
import com.module.model.MessageInfo;
import com.module.model.UserInfo;
import com.module.service.MessageService;
import com.module.service.UserService;
import com.module.utils.CheckSumBuilder;
import com.module.utils.DateUtil;
import com.module.utils.IDUtil;
import com.module.utils.MD5Util;
import com.module.utils.push.PushSender;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpSession;

import static com.module.listen.SessionListener.LISTENER_NAME;
import static com.module.utils.DateUtil.FORMAT_LONG;

@Controller
@RequestMapping(produces = {"application/json;charset=UTF-8"}, value = {"/userCenter"})
@Api(description = "用户模块接口")
public class UserController extends BaseController {

    @Autowired
    private UserService userService;

    @Autowired
    private MessageService messageService;


    @ApiOperation(value = "用户密码登陆")
    @RequestMapping(value = {"/login"}, method = {RequestMethod.POST})
    @ResponseBody
    public BaseResp<UserInfo> loginByPwd(@RequestBody LoginReq req,@ApiIgnore HttpSession session) {
        BaseResp resp = new BaseResp();
 
        String mobile = req.getMobile();
        String pwd = req.getPwd();
 
        if (StringUtils.isEmpty(mobile)) {
            resp.setStatus(-1);
            resp.setMessage("手机号码为空");
            return resp;
        }
 
        if (StringUtils.isEmpty(pwd)) {
            resp.setStatus(-1);
            resp.setMessage("密码为空");
            return resp;
        }
 
        UserInfo userInfo = this.userService.getUserByMobile(mobile);
        if (userInfo == null) {
            resp.setStatus(-1);
            resp.setMessage("用户不存在");
            return resp;
        }
        MD5Util md5Util=new MD5Util(userInfo.getSalt());
        if(!md5Util.isPasswordValid(userInfo.getUserPwd(),pwd)){
            resp.setStatus(-1);
            resp.setMessage("密码错误");
            return resp;
        }
        userInfo.setPushId(req.getPushId());
        this.userService.modifyUser(userInfo);
        sendMessage(userInfo.getId(), req.getPushId());
        userInfo.setUserPwd(null);
        resp.setStatus(0);
        resp.setMessage("登录成功");
        resp.setData(userInfo);
        session.setAttribute(LISTENER_NAME, SessionListener.getSessions().add(new OnlineSession(request.getRemoteAddr(),userInfo.getUserName(),DateUtil.getNow())));
        return resp;
    }

    private void sendMessage(Integer userId, String pushId) {
        String curTime = DateUtil.format(new Date(), DateUtil.FORMAT_LONG_NEW);
        MessageInfo msg = new MessageInfo();
        msg.setMsgIcon("http://osea2fxp7.bkt.clouddn.com/108x108.png");
        msg.setMsgTitle("登录成功");
        msg.setMsgContent("恭喜您登录成功");
        msg.setMsgTime(curTime);
        msg.setUserId(userId);
        this.messageService.addMessage(msg);
 
        PushSender.sendLoginEvent(pushId);
    }

    @ApiOperation(value = "忘记密码找回密码")
    @RequestMapping(value = {"/forgetPwd"}, method = {RequestMethod.POST})
    @ResponseBody
    public BaseResp forgetPwd(@RequestBody ForgetPwdReq req) {
        BaseResp resp = new BaseResp();
 
        String mobile = req.getMobile();
        String verifyCode = req.getVerifyCode();
 
        if (StringUtils.isEmpty(mobile)) {
            resp.setStatus(-1);
            resp.setMessage("手机号码为空");
            return resp;
        }
 
        if (StringUtils.isEmpty(verifyCode)) {
            resp.setStatus(-1);
            resp.setMessage("验证码为空");
            return resp;
        }
 
        UserInfo userInfo = this.userService.getUserByMobile(mobile);
        if (userInfo == null) {
            resp.setStatus(-1);
            resp.setMessage("用户不存在");
            return resp;
        }
        if( session.getAttribute("code")==null){
            resp.setStatus(-1);
            resp.setMessage("验证码错误");
            return resp;
        }else {
            if (!session.getAttribute("code").equals(verifyCode)) {
                resp.setStatus(-1);
                resp.setMessage("验证码错误");
                return resp;
            }
        }

        resp.setStatus(0);
        resp.setMessage("验证成功");
        return resp;
    }

    @ApiOperation(value = "重置密码")
    @RequestMapping(value = {"/resetPwd"}, method = {RequestMethod.POST})
    @ResponseBody
    public BaseResp<String> resetPwd(@RequestBody ModifyPwdReq req) {
        BaseResp resp = new BaseResp();
 
        String mobile = req.getMobile();
        String pwd = req.getPwd();
 
        if (StringUtils.isEmpty(mobile)) {
            resp.setStatus(-1);
            resp.setMessage("手机号码为空");
            return resp;
        }
 
        if (StringUtils.isEmpty(pwd)) {
            resp.setStatus(-1);
            resp.setMessage("密码为空");
            return resp;
        }
 
        UserInfo userInfo = this.userService.getUserByMobile(mobile);
        if (userInfo == null) {
            resp.setStatus(-1);
            resp.setMessage("用户不存在");
            return resp;
        }
        MD5Util md5Util=new MD5Util(userInfo.getSalt());
        String pass=md5Util.encode(req.getPwd());
        userInfo.setUserPwd(pwd);
        int result = this.userService.modifyUser(userInfo);
 
        if (result > 0) {
            resp.setStatus(0);
            resp.setMessage("密码修改成功");
            return resp;
        }
        resp.setStatus(-1);
        resp.setMessage("密码修改失败");
        return resp;
    }

    @ApiOperation(value = "注册")
    @RequestMapping(value = {"/register"}, method = { RequestMethod.POST})
    @ResponseBody
    public BaseResp register(@RequestBody RegisterReq req,@ApiIgnore HttpSession session) {
        BaseResp resp = new BaseResp();
 
        String mobile = req.getMobile();
        String verifyCode = req.getVerifyCode();
 
        UserInfo userInfo = this.userService.getUserByMobile(mobile);
        if (userInfo != null) {
            resp.setStatus(-1);
            resp.setMessage("账号已被注册");
            return resp;
        }
        if( session.getAttribute("code")==null){
            resp.setStatus(-1);
            resp.setMessage("验证码错误");
            return resp;
        }else {
            if (!session.getAttribute("code").equals(verifyCode)) {
                resp.setStatus(-1);
                resp.setMessage("验证码错误");
                return resp;
            }
        }

        userInfo = new UserInfo();
        userInfo.setUserMobile(mobile);
        userInfo.setUserName(mobile);

        userInfo.setRoleid(2);
        userInfo.setStatus(0);
        userInfo.setCreatetime(new Date());
        String salt =MD5Util.createSalt(5);
        MD5Util md5Util=new MD5Util(salt);
        String pass=md5Util.encode(req.getPwd());
        userInfo.setUserGender("1");
        userInfo.setSalt(salt);
        userInfo.setUserPwd(pass);
        this.userService.addUser(userInfo);
        resp.setStatus(0);
        return resp;
    }

    @ApiOperation(value = "编辑用户")
    @RequestMapping(value = {"/editUser"}, method = { RequestMethod.POST})
    @ResponseBody
    public BaseResp<UserInfo> editUser(@RequestBody EditUserReq req) {
        BaseResp resp = new BaseResp();
 

        UserInfo info=userService.selectById(req.getId());

        info.setUserName(req.getUserName());
        info.setUserIcon(req.getUserIcon());
        info.setUserGender(req.getUserGender());
        info.setUserSign(req.getSign());
        info.setUpdatetime(new Date());
        info.setUserAddress(req.getUserAddress());
        info.setUserBirthday(req.getUserBirthday());
        this.userService.modifyUser(info);
 
        resp.setStatus(0);
        resp.setData(info);
        return resp;
    }

    @ApiOperation("获取手机验证码")
    @RequestMapping(value = {"/getcode"}, method = { RequestMethod.POST})
    @ResponseBody
    public BaseResp<UserInfo> getCode(@ApiParam("手机号码") @RequestParam String phone, HttpSession session) {
        /*
         * 现在 DefaultHttpClient已经过时了
         * DefaultHttpClient继承AbstractHttpClient
         * AbstractHttpClient继承CloseableHttpClient
         * CloseableHttpClient通过HttpClients的createDefault方法创建
         */
        BaseResp resp = new BaseResp();
        CloseableHttpClient httpclient = HttpClients.createDefault();
        //post请求
        HttpPost httpPost = new HttpPost(Constant.SERVER_URL);
        //时间戳
        String curTime = String.valueOf((new Date()).getTime() / 1000L);
        //生产短信验证码
        String code = IDUtil.generateSmsCode();

        /*
         * 参考计算CheckSum的java代码，在上述文档的参数列表中，有CheckSum的计算文档示例
         */
        String checkSum = CheckSumBuilder.getCheckSum(Constant.APP_SECRET, code, curTime);

        // 设置请求的header
        httpPost.addHeader("AppKey", Constant.APP_KEY);
        httpPost.addHeader("Nonce", code);
        httpPost.addHeader("CurTime", curTime);
        httpPost.addHeader("CheckSum", checkSum);
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

        // 设置请求的的参数，requestBody参数
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        /*
         * 1.如果是模板短信，请注意参数mobile是有s的，详细参数配置请参考“发送模板短信文档”
         * 2.参数格式是jsonArray的格式，例如 "['13888888888','13666666666']"
         * 3.params是根据你模板里面有几个参数，那里面的参数也是jsonArray格式
         */
        nvps.add(new BasicNameValuePair("templateid", Constant.TEMPLATEID));
        nvps.add(new BasicNameValuePair("mobile", phone));
        nvps.add(new BasicNameValuePair("codeLen", Constant.CODELEN));

        CloseableHttpResponse responsecode=null;
        try {
            //设置编码格式
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            //执行请求并返回CloseableHttpResponse
            responsecode = httpclient.execute(httpPost);
            //获取返回结果
            HttpEntity entity = responsecode.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                //直接返回json字符串给客户端验证

                JSONObject jsonObject=JSONObject.parseObject(result);
                if( jsonObject.get("code").toString().equals("200")){
                    session.setAttribute("code",(String) jsonObject.get("obj"));
                    resp.setStatus(0);
                    resp.setMessage((String) jsonObject.get("obj"));
                }else {
                    resp.setStatus(500);
                    resp.setMessage("获取验证码失败！");
                }

                return resp;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(responsecode != null){
                try {
                    responsecode.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(httpclient != null){
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}
